#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>

#define FAILED		0
#define SUCCESS		1

#define PROC_NUM	1024
#define MAX_ALLOC_BYTES	1024
#define MAX_CHAR	51

/*
	For comments on the functions please go to the definition .
*/

BOOL getProcID(LPDWORD lpdwPID);
BOOL hooking(DWORD dwPID);
VOID myFunc(PCHAR pName);
VOID pause();

/*
	Global (for now) Target exe & DLL location
*/
CHAR TARGET[101] = {'\0'};
CHAR DLL_LOC[151] = {'\0'};

int main()
{
	DWORD dwPID = 0;					//Will store the TARGET's PID .

	printf("Please enter a target .exe (example: notepad.exe):\t");
	fgets(TARGET,100,stdin);			//Get target
	TARGET[strlen(TARGET) - 1] = '\0';

	printf("\nPlease enter a full path to the dll (even if its in the same dir)\nIf an error occurse - run as admin:\n");
	fgets(DLL_LOC,150,stdin);
	DLL_LOC[strlen(DLL_LOC) -1] = '\0';

	if ( FAILED == getProcID(&dwPID) )	//Get TARGET's PID
	{
		printf("Failed .");
		pause();
		return 1;
	}//if

	if ( FAILED == hooking(dwPID) )		//Try the API hooking
	{
		printf("Failed .");
		pause();
		return 1;
	}//if

	pause();
	return 0;
}//main

/*
	Will get the TARGET's PID to use with OpenProcess() for API hooking .
*/
BOOL getProcID(LPDWORD lpdwPID)
{
	HANDLE hProc = INVALID_HANDLE_VALUE;		//Handle
	PROCESSENTRY32 pe32 = {0};					//PE32 struct (stores process info)

	hProc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,	//Create snapshot
										0);

	if (INVALID_HANDLE_VALUE == hProc)
	{
		CloseHandle(hProc);
		return FAILED;
	}//if

	pe32.dwSize = sizeof(PROCESSENTRY32);	//Initialize size for Process32First

	while ( strcmp (pe32.szExeFile , TARGET ) != 0 )	//Try to get first appearance of target exe .
	{
		if ( !Process32Next(hProc ,&pe32) )
		{
			CloseHandle(hProc);
			return FAILED;
		}//if
	}//while

	
	*lpdwPID = pe32.th32ProcessID;			//Set PID
	CloseHandle(hProc);
	
	return SUCCESS;
}//getProcID

BOOL hooking(DWORD dwPID)
{
	HANDLE hProc = INVALID_HANDLE_VALUE;	//Handle to the process
	HANDLE hThread = INVALID_HANDLE_VALUE;	//Handle to a new remote thread
	LPVOID lpAlloc = NULL;					//Pointer to virtual allocated mem in the new thread .

	LPVOID lpArg = NULL;
	INT len = strlen(DLL_LOC);

	if ( !( hProc = OpenProcess( (PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_VM_WRITE), FALSE , dwPID ) ) )	//Grant VM_Operation permissions on the exe
	{
		CloseHandle(hProc);
		return FAILED;
	}//if

	/*
		test use remote thread
	*/

	if ( !( lpArg = VirtualAllocEx(hProc, NULL, len + 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE ) ) )
	{
		CloseHandle(hProc);
		return FAILED;
	}//if

	if ( !( WriteProcessMemory(hProc, lpArg, DLL_LOC, len, NULL) ) )
	{
		CloseHandle(hProc);
		return FAILED;
	}//if

	lpAlloc = 	GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");

	if ( !( hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpAlloc, lpArg, 0, NULL ) ) ) //Create remote thread & execute
	{
		CloseHandle(hThread);
		CloseHandle(hProc);
		return FAILED;
	}//if

	return SUCCESS;
}//hooking

VOID myFunc(PCHAR pName)
{
	HANDLE hFile = INVALID_HANDLE_VALUE;
	DWORD dwNobw = 0;

	hFile = CreateFile(
				pName,
				GENERIC_WRITE,
				0,
				NULL,
				CREATE_ALWAYS,
				0,
				NULL);

	WriteFile(
		hFile,
		"test",
		4,
		&dwNobw,
		NULL);

	CloseHandle(hFile);
	return;
}//myFunc

VOID pause()
{
	printf("Press any key .");
	getch();
	return;
}//pause